/**
 * 
 */
package org.t2.backstage.module.player.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.banish.sql.core.dao.Dao;
import org.banish.sql.core.datasource.IDataSource;
import org.banish.sql.core.util.QuerySet;
import org.gaming.ruler.schedule.LoopingTask;
import org.gaming.service.repository.Repository;
import org.gaming.service.service.AbstractService;
import org.gaming.tool.DateTimeUtil;
import org.gaming.tool.ListMapUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.t2.backstage.module.gameserver.model.GameServer;
import org.t2.backstage.module.gameserver.service.DataBaseManager;
import org.t2.backstage.module.gameserver.service.GameServerService;
import org.t2.backstage.module.player.model.PlayerSummary;
import org.t2.backstage.module.system.model.SystemCounter;
import org.t2.backstage.module.system.service.SystemCounterService;

import sh.t2.share.module.player.log.PlayerCreateLog;
import sh.t2.share.module.player.log.PlayerLoginLog;
import sh.t2.share.module.player.log.PlayerRechargeLog;

/**
 * 
 */
@Service
public class PlayerSummaryService extends AbstractService<PlayerSummary> {

	@Autowired
	private GameServerService gameServerService;
	@Autowired
	private DataBaseManager dataBaseManager;
	@Autowired
	private SystemCounterService systemCounterService;
	
	public void insertUpdate(List<PlayerSummary> summarys) {
		this.repository().getBaseDao().insertUpdate(summarys);
	}
	
	@LoopingTask(name = "PlayerTimer-基础数据统计", spaceTime = DateTimeUtil.ONE_SECOND_MILLIS * 10, execGroup = 6)
	private void runInSchedule() {
		SystemCounter systemCounter = systemCounterService.instance();
		if(DateTimeUtil.currMillis() < systemCounter.getSummaryTime()) {
			return;
		}
		systemCounter.setSummaryTime(DateTimeUtil.tomorrowZeroMillis());
		systemCounterService.update(systemCounter);
		
		countSummary(DateTimeUtil.todayZeroMillis());
	}
	
	/**
	 * 统计留存
	 * @param dateTime 某天的任一时间点
	 */
	public void countSummary(long dateTimeMillis) {
		//今天统计的是昨天的数据
		dateTimeMillis = dateTimeMillis - DateTimeUtil.ONE_DAY_MILLIS;
		
		String currYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, dateTimeMillis);
		logger.info("开始{}的基础数据统计", currYMD);
		
		List<GameServer> gameServers = gameServerService.getEntityList(0);
		for(GameServer gameServer : gameServers) {
			logger.info("进行服务器{}-{}的基础数据统计", gameServer.getId(), gameServer.getName());
			querySummaryLog(gameServer, dateTimeMillis);
		}
		logger.info("完成{}的基础数据统计", currYMD);
	}
	
	public void querySummaryLog(GameServer gameServer, long dateTimeMillis) {
		IDataSource dataBase = dataBaseManager.getLogDb(gameServer.getId());
		if(dataBase == null) {
			logger.error("服务器{}-{}的基础数据统计中，未找到数据库连接信息", gameServer.getId(), gameServer.getName());
			return;
		}
		
		Map<Long, List<PlayerCreateLog>> channelCreateMap = queryCreageLog(dataBase, dateTimeMillis);
		Map<Long, List<PlayerRechargeLog>> channelRechargeMap = queryRechargeLog(dataBase, dateTimeMillis);
		Map<Long, List<PlayerLoginLog>> channelLoginMap = queryLoginLog(dataBase, dateTimeMillis);
		
		Set<Long> channelIds = new HashSet<>();
		channelIds.addAll(channelCreateMap.keySet());
		channelIds.addAll(channelRechargeMap.keySet());
		channelIds.addAll(channelLoginMap.keySet());
		int summaryDate = Integer.parseInt(DateTimeUtil.formatMillis(DateTimeUtil.YYYYMMDD, dateTimeMillis));
		
		List<PlayerSummary> playerSummarys = new ArrayList<>();
		
		for(long channelId : channelIds) {
			PlayerSummary playerSummary = new  PlayerSummary();
			playerSummary.setChannelId(channelId);
			playerSummary.setServerUid(gameServer.getId());
			playerSummary.setSummaryDate(summaryDate);
			
			List<PlayerCreateLog> createLogs = channelCreateMap.get(channelId);
			if(createLogs != null) {
				playerSummary.setNewPlayerCount(createLogs.size());
			}
			
			List<PlayerRechargeLog> rechargeLogs = channelRechargeMap.get(channelId);
			if(rechargeLogs != null) {
				long totalPay = 0;
				long newComerPay = 0;
				long oldComerPay = 0;
				//付费人数
				Set<Long> playerIds = new HashSet<>();
				Set<Long> newComerPlayerIds = new HashSet<>();
				Set<Long> oldComerPlayerIds = new HashSet<>();
				
				for(PlayerRechargeLog log : rechargeLogs) {
					playerIds.add(log.getPlayerId());
					
					totalPay += log.getMoney();
					//当天创号的新注册账号记为新账号人数
					if(log.getBornDate() == log.getRechargeDate() && log.isNewComer()) {
						newComerPlayerIds.add(log.getPlayerId());
						newComerPay += log.getMoney();
					} else {
						oldComerPlayerIds.add(log.getPlayerId());
						oldComerPay += log.getMoney();
					}
				}
				
				playerSummary.setTotalPay(totalPay);
				playerSummary.setPayPlayerCount(playerIds.size());
				playerSummary.setNewComerPayCount(newComerPlayerIds.size());
				playerSummary.setNewComerPayMoney(newComerPay);
				playerSummary.setOldComerPayCount(oldComerPlayerIds.size());
				playerSummary.setOldComerPayMoney(oldComerPay);
			}
			
			List<PlayerLoginLog> loginLogs = channelLoginMap.get(channelId);
			if(loginLogs != null) {
				Set<Long> playerIds = new HashSet<>();
				for(PlayerLoginLog log : loginLogs) {
					playerIds.add(log.getPlayerId());
				}
				playerSummary.setPlayerDau(playerIds.size());
			}
			playerSummarys.add(playerSummary);
		}
		this.insertUpdate(playerSummarys);
	}
	
	public Map<Long, List<PlayerLoginLog>> queryLoginLog(IDataSource dataBase, long dateTimeMillis) {
		String yearMonth = DateTimeUtil.formatMillis(DateTimeUtil.YYYYMM, dateTimeMillis);
		String tableName = Repository.getTableName(PlayerLoginLog.class) + "_" + yearMonth;
		
		String currYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, dateTimeMillis);
		long nextDateTime = dateTimeMillis + DateTimeUtil.ONE_DAY_MILLIS;
		String nextYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, nextDateTime);
		
		String playerCreateLogSql = "select * from " + tableName + " ";
		QuerySet querySet = new QuerySet();
		querySet.addCondition("login_time >= ?", currYMD);
		querySet.addCondition("login_time < ?", nextYMD);
		querySet.formWhere();
		String sql = playerCreateLogSql + querySet.getWhere();
		List<PlayerLoginLog> logs = Dao.queryAliasObjects(dataBase, PlayerLoginLog.class, sql, querySet.getParams());
		return ListMapUtil.fillListMap(logs, PlayerLoginLog::getChannelId);
	}
	
	public Map<Long, List<PlayerCreateLog>> queryCreageLog(IDataSource dataBase, long dateTimeMillis) {
		String currYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, dateTimeMillis);
		long nextDateTime = dateTimeMillis + DateTimeUtil.ONE_DAY_MILLIS;
		String nextYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, nextDateTime);
		
		String playerCreateLogSql = "select * from player_create_log ";
		QuerySet querySet = new QuerySet();
		querySet.addCondition("born_time >= ?", currYMD);
		querySet.addCondition("born_time < ?", nextYMD);
		querySet.formWhere();
		String sql = playerCreateLogSql + querySet.getWhere();
		
		List<PlayerCreateLog> logs = Dao.queryAliasObjects(dataBase, PlayerCreateLog.class, sql, querySet.getParams());
		return ListMapUtil.fillListMap(logs, PlayerCreateLog::getChannelId);
	}
	
	public Map<Long, List<PlayerRechargeLog>> queryRechargeLog(IDataSource dataBase, long dateTimeMillis) {
		String currYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, dateTimeMillis);
		long nextDateTime = dateTimeMillis + DateTimeUtil.ONE_DAY_MILLIS;
		String nextYMD = DateTimeUtil.formatMillis(DateTimeUtil.YYYY_MM_DD, nextDateTime);
		
		String playerRechargeLogSql = "select * from player_recharge_log ";
		QuerySet querySet = new QuerySet();
		querySet.addCondition("recharge_time >= ?", currYMD);
		querySet.addCondition("recharge_time < ?", nextYMD);
		querySet.formWhere();
		String sql = playerRechargeLogSql + querySet.getWhere();
		List<PlayerRechargeLog> logs = Dao.queryAliasObjects(dataBase, PlayerRechargeLog.class, sql, querySet.getParams());
		return ListMapUtil.fillListMap(logs, PlayerRechargeLog::getChannelId);
	}
	
	public List<PlayerSummary> querySummary(QuerySet query) {
		return this.repository().getBaseDao().queryListWhere(query.getWhere(), query.getParams());
	}
	
	@Override
	public void mergeServer(int mergeDbZoneId) {
		//不用实现
	}
}
